﻿/*
 * @Author: Song Xinxin
 * @Date: 2022-10-28 11:36:26
 * @LastEditors: Song Xinxin
 * @LastEditTime: 2022-11-07 11:49:00
 * @FilePath: \WYW_0419_Oasis\JavaScripts\Modules\Weapon\Module_Weapon.ts
 * @Description: 武器模块
 * 
 * Copyright (c) 2022 by error: git config user.name && git config user.email & please set dead value or install git, All Rights Reserved. 
 */
import { EffectManager, ModuleC, ModuleManager, ModuleS, SoundManager } from "odin";
import { Consts } from "../../Consts";
import { ModuleS_NPC } from "../NPC/Module_NPC";
import { ModuleS_PlayerAttr } from "../PlayerAttr/Module_PlayerAttr";
import { ModuleS_Skill } from "../Skill/Module_Skill";
import { ModuleS_Sound } from "../Sound/Module_Sound";

/**
 * 武器模块服务端
 */
export class ModuleS_Weapon extends ModuleS<ModuleC_Weapon,null>
{

	/**
	 * 播放开枪音效
	 * @param loc 枪口位置
	 */
	public net_shootSound(loc:Type.Vector):void
	{
		ModuleManager.instance.getModule(ModuleS_Sound).shootSound(loc);
	}

	/**
	 * 播放击中特效
	 * @param pos 击中位置
	 */
	public net_hitEffect(pos:Type.Vector):void
	{
		EffectManager.instance.playEffectInPos(Consts.BULLET_HIT_EFFECT_GUID,pos,1);
		ModuleManager.instance.getModule(ModuleS_Sound).hitSound(pos);
	}

	/**
	 * 在角色初生点旁生成武器
	 * @param player 进入游戏的玩家
	 * @returns 返回武器
	 */
	public async createWeapon(player:GamePlay.Player):Promise<void>
	{
		//生成武器
		let weapon = await MWCore.GameObject.asyncSpawnGameObject(Consts.GUN_GUID,true);
		this.callClientFun(player,this.client.net_Weapon(weapon));
		let loc = player.character.location;
		weapon.location = new Type.Vector(loc.x,loc.y+100,loc.z-150);
		weapon.setCollision(Type.CollisionStatus.Off);
		//生成光圈特效
		let weapon_effect_id = EffectManager.instance.playEffectInGameObject(Consts.GUN_EFFECT_GUID,weapon,0,Type.Vector.zero,Type.Rotation.zero,Type.Vector.one);

		//生成拾取武器的触发器
		if(GamePlay.isServer())
		{
			let trigger = await MWCore.GameObject.asyncSpawnGameObject(Consts.TRIGGER_GUID,true) as GamePlay.Trigger;
			trigger.location = weapon.location;
			trigger.onEnter.add((gameobject)=>
			{	
				if(GamePlay.isCharacter(gameobject))
				{
					//玩家进入触发器后拾取武器
					let player = (gameobject as GamePlay.CharacterBase).player
					this.pickWeapon(weapon,player);
					//停止播放光圈特效
					EffectManager.instance.stopEffect(weapon_effect_id);
					//销毁触发器
					trigger.destroy();
				}
			})
		}


	}


	/**
	 * 销毁武器
	 * @param player 当前玩家
	 */
	public net_destroyWeapon(weapon:MWCore.GameObject):void
	{
		this.currentPlayer.character.ragdoll(false);
		weapon.destroy();
	}

	/**
	 * 拾取武器
	 * @param weapon 拾取的武器
	 * @param player 拾取武器的玩家
	 */
	public pickWeapon(weapon:MWCore.GameObject,player:GamePlay.Player):void
	{
		//把武器挂载到玩家右手上
		player.character.attachGameObjectToCharacter(weapon,GamePlay.CharacterSocketType.Right_Hand);
		//调整武器位置和朝向
		weapon.setRelativeLocation(new Type.Vector(15, 0, -10));
		weapon.setRelativeRotation(new Type.Rotation(0,8,0));

		//玩家变成持枪姿势
		player.character.animationStance = Consts.HOLD_GUN_GUID;
		// 玩家朝向模式改为控制器方向
		player.character.moveFacingDirection = GamePlay.MoveFacingDirection.ControllerDirection;

		//解锁射击
		ModuleManager.instance.getModule(ModuleS_Skill).UnlockShoot(player);
	}

	/**
	 * 击中玩家
	 * @param player 开枪的玩家
	 * @param hitplayer 被击中的玩家
	 */
	public net_hitplayer(player:GamePlay.Player,hitplayer:GamePlay.Player):void
	{
		ModuleManager.instance.getModule(ModuleS_PlayerAttr).hitPlayer(player,hitplayer);
	}

	public net_hitNPC(player:GamePlay.Player,NPC:GamePlay.Humanoid):void
	{
		ModuleManager.instance.getModule(ModuleS_NPC).hitNPC(player,NPC);
	}

}

/**
 * 武器模块客户端
 */
export class ModuleC_Weapon extends ModuleC<ModuleS_Weapon,null>
{

	//玩家获得的武器
	Weapon:MWCore.GameObject;
	//开枪定时器
	Interval:number;

	/**
	 * 获取玩家获得的武器
	 * @param weapon 玩家手上的武器
	 */
	public net_Weapon(weapon:MWCore.GameObject):void
	{
		this.Weapon = weapon;
	}

	/**
	 * 销毁武器
	 */
	public destroyweapon():void
	{
		this.server.net_destroyWeapon(this.Weapon);
	}

	/**
	 * 开枪射击
	 * @param weapon 玩家持有的武器
	 * @returns 定时器
	 */
	public startshoot():void
	{
		//切换为开枪姿态
		this.currentPlayer.character.animationStance = Consts.SHOOT_ATTITUDE_GUID;

		//每隔一定的攻击间隔进行一次射线检测
		this.Interval = setInterval(()=>
		{
			let loc = new Type.Vector(this.Weapon.getForwardVector().mul(20).add(this.Weapon.location)); 
			this.server.net_shootSound(loc);
			//射线检测
			let res = GamePlay.lineTrace(this.Weapon,loc,(this.Weapon.getForwardVector().mul(Consts.WeaponAttr.range)).add(loc),false,false);
			//击中物体
			if(res.length > 0)
			{
				let chara = res[0].gameObject;
				this.server.net_hitEffect(res[0].location);
				//击中角色
				if(chara instanceof GamePlay.Character)
				{
					//击中玩家
					let hitplayer = (chara as GamePlay.CharacterBase).player;
					this.server.net_hitplayer(this.currentPlayer,hitplayer);
					
				}
				else if(chara instanceof GamePlay.Humanoid)
				{
					//击中NPC
					let NPC = chara as GamePlay.Humanoid;
					this.server.net_hitNPC(this.currentPlayer,NPC);

				}
				
			}
		},Consts.WeaponAttr.cooldown*1000)

	}

	/**
	 * 停止射击
	 * @param interval 定时器
	 */
	public stopshoot():void
	{
		if(this.Interval != null)
		{
			//清除射击的定时器
			clearInterval(this.Interval);
			//切换为持枪姿态
			this.currentPlayer.character.animationStance = Consts.HOLD_GUN_GUID;
		}
	}

}
